/**
 * Copyright 2018 orivil.com. All rights reserved.
 * Use of this source code is governed by a MIT-style
 * license that can be found at https://mit-license.org.
 */

package model

import (
	"golang.org/x/crypto/bcrypt"
	"github.com/jinzhu/gorm"
	"time"
	"errors"
	"gitee.com/tugoer/psy-testing/code/env"
)

var (
	ErrWrongUsername = errors.New("用户名错误")
	ErrWrongPassword = errors.New("密码错误")
	ErrNotAllowedLogin = errors.New("该账户已被禁止登陆")
)

type Admin struct {
	ID int
	Name string `gorm:"unique_index"`
	Password string
	Email string `gorm:"index"`
	AllowedLogin bool // 允许登陆
	Parent int `gorm:"index"`
	CreatedAt *time.Time
}

// 创建管理员，该动作只能在系统内部操作，如初始化系统时创建超级管理员，不可提供接口给客户端
func (a *Admin)Create() error {
	pass, err := bcrypt.GenerateFromPassword([]byte(a.Password), 0)
	if err != nil {
		return err
	}
	a.Password = string(pass)
	return env.GormDB.Create(a).Error
}

func AdminCreateChild(parent int, a *Admin) error {
	a.Parent = parent
	a.AllowedLogin = true
	pass, err := bcrypt.GenerateFromPassword([]byte(a.Password), 0)
	if err != nil {
		return err
	}
	a.Password = string(pass)
	return env.GormDB.Create(a).Error
}

func GetChildren(parent int) (as []*Admin, err error) {
	errs := env.GormDB.Where("parent=?", parent).Find(&as).GetErrors()
	for _, e := range errs {
		if e != nil && e != gorm.ErrRecordNotFound {
			return nil, e
		}
	}
	return
}

func AdminUpdatePassword(loginName, password string) error {
	pass, err := bcrypt.GenerateFromPassword([]byte(password), 0)
	if err != nil {
		return err
	}
	return env.GormDB.Model(Admin{}).Where("name=?", loginName).Update(map[string]string{
		"password": string(pass),
	}).Error
}

func AdminUpdateChild(parentID int, childName string, password string, allowedLogin bool) error {
	var data = make(map[string]interface{}, 2)
	if password != "" {
		pass, err := bcrypt.GenerateFromPassword([]byte(password), 0)
		if err != nil {
			return err
		}
		data["password"] = string(pass)
	}
	data["allowed_login"] = allowedLogin
	return env.GormDB.Model(Admin{}).Where("name=? AND parent=?", childName, parentID).Update(data).Error
}

// AdminLogin 登陆管理员,
// 密码错误返回 ErrWrongPassword
// 账号错误返回 ErrWrongUsername
// 禁止登陆返回 ErrNotAllowedLogin
// 其他返回未知错误
func AdminLogin(name, password string) (a *Admin, err error) {
	a = &Admin{}
	err = env.GormDB.Where("name=?", name).Find(a).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, ErrWrongUsername
		} else {
			return nil, err
		}
	}
	if !a.AllowedLogin {
		return nil, ErrNotAllowedLogin
	}
	err = bcrypt.CompareHashAndPassword([]byte(a.Password), []byte(password))
	if err != nil {
		if err == bcrypt.ErrMismatchedHashAndPassword {
			return nil, ErrWrongPassword
		} else {
			return nil, err
		}
	}
	return a, nil
}